Hello, everyone~~
昨天練習了利用Active Record Query Interface 與SQL statements 來query 的方法,今天想趁機試試此前很常看到的SQL injection
~~
SQL injection 是什麼呢?Rails Guide是這麼解釋的:
SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data.
**翻譯蒟蒻:SQL injection 是藉著污染傳入query 語句內的params 來操弄資料庫的行為
我們來跟著試試看:
# pure string 寫法
irb(main):006:0> Post.where("body = 'IThome1'")
# params 寫法:
irb(main):017:0> params = { body: "IThome1" }
irb(main):014:0> Post.where("body = ?", params[:body])
Post Load (0.9ms) SELECT "posts".* FROM "posts" WHERE (body = 'IThome1')
上面的寫法是比較安全的,但若使用string interpolation 也能得到同樣結果:
irb(main):016:0> Post.where("body = '#{params[:body]}'")
Post Load (0.7ms) SELECT "posts".* FROM "posts" WHERE (body = 'IThome1')
然而這種寫法就容易導致SQL injection:
# 同上的params
params = { body: "IThome1" }
# 在application 上帶入params 時,大多會有id 欄位的資料連同被回傳
params = params.merge(id: 1)
# 此時若id params 被污染了
params[:id] = "1) OR 1=1--"
# query 就會回傳不該出現的資料
Post.where("id = #{params[:id]}")
# here
irb(main):010:0> Post.where("id = #{params[:id]}").count
(0.8ms) SELECT COUNT(*) FROM "posts" WHERE (id = 1) OR 1=1--)
100
可從上述最後一個query statement 和結果筆數看到全部資料都被叫出來了,若這時搭配的方法是delete_by
就真的掰了:
irb(main):010:0> Post.delete_by("id = #{params[:id]}")
Post Destroy (0.7ms) DELETE FROM "posts" WHERE (id = 1) OR 1=1--)
100
# 或
irb(main):011:0> post = Post.where("id = #{params[:id]}")
irb(main):012:0> post.update(title: "SQL injection badbad")
但為什麼1) OR 1=1--"
會影響那麼大呢?
這可以分成幾個部分理解:1)
: 即強迫完成了前句的query:Post.where("id = 1)
")OR
: 或是1=1
: 因前句(id = 1) 為true 加上或是1=1 為true,則每一筆資料都被選取了--
: SQL 的註解符號,即無效化後方的statement,就藉機排除了syntax error
即:SELECT COUNT(*) FROM "posts" WHERE (id = 1) OR 1=1--)
所以追中才會導致每筆資料都被選起來處理啦~~
雖然SQL injection 要剛好遇到可被污染的情境(欄位、語句)及方法(如query 的欄位形態 + delete_by vs. delete),可會做這種事的大大功力應該不容小覷,若server 恰巧沒驗證阻擋或沒預警管理員,屆時可能為時已晚啦~
那今天就先研究到這裡囉,謝謝大家~~
參考資料:
Rails 實作 SQL Injection | wells's blog
4. SQL Injection 資料庫注入攻擊 - Rails 實戰聖經
Rails SQL Injection Examples
Rails SQL Injection Guide: Examples and Prevention